/********************************************
* Copyrigt (C) rumi
* Module: Ser_CircleBuffer.c
* History: Created on 2021.8.10
* Version:1.0.0 add ros2 support
*********************************************/
#include "ser_circlebuffer.h"

/************************************************************************
* CBuff_Init
************************************************************************/
void CBuff_Init(CBuff *buffer, uint8_t *pBuff, uint32_t size)
{
    buffer->pBuff = pBuff;
    buffer->Size = size;
    buffer->Head = 0;
    buffer->Tail = 0;
}

/************************************************************************
* CBuff_GetLength
************************************************************************/
uint32_t CBuff_GetLength(const CBuff *buffer)
{
    return (buffer->Head >= buffer->Tail) ? (buffer->Head - buffer->Tail) : (buffer->Size + buffer->Head - buffer->Tail);
}

/************************************************************************
* CBuff_Write
************************************************************************/
bool CBuff_Write(CBuff *buffer, const uint8_t *data, uint32_t len)
{
    uint32_t freeSpace = buffer->Size - CBuff_GetLength(buffer) - 1; 
    uint32_t Head,i;

    if (freeSpace < len)
    {
        return false; 
    }

    Head = buffer->Head;
    for (i = 0; i < len; i++)
    {
        buffer->pBuff[Head] = data[i];
        Head = (Head + 1) % buffer->Size;
    }
    buffer->Head = Head;

    return true; 
}
/************************************************************************
* CBuff_Read
************************************************************************/
bool CBuff_Read(CBuff *buffer, uint8_t *data, uint32_t len)
{
    uint32_t availableData = CBuff_GetLength(buffer);
    uint32_t Tail,i;

    if (availableData < len)
    {
        return false; 
    }
    
    Tail = buffer->Tail;
    for (i = 0; i < len; i++)
    {
        data[i] = buffer->pBuff[Tail];
		Tail = (Tail + 1) % buffer->Size;
    }
    
    return true; 
}
/************************************************************************
* CBuff_Pop
************************************************************************/
bool CBuff_Pop(CBuff *buffer, uint8_t *data, uint32_t len)
{
    uint32_t availableData = CBuff_GetLength(buffer);
    uint32_t Tail,i;

    if (availableData < len)
    {
        return false; 
    }
    
    Tail = buffer->Tail;
    for (i = 0; i < len; i++)
    {
        data[i] = buffer->pBuff[Tail];
        Tail = (Tail + 1) % buffer->Size;
    }
    buffer->Tail = Tail;
    return true; 
}

/************************************************************************
* CBuff_Clear
************************************************************************/
void CBuff_Clear(CBuff *buffer)
{
    buffer->Head = 0;
    buffer->Tail = 0;
}

/************************************************************************
* CBuff_IsEmpty
************************************************************************/
bool CBuff_IsEmpty(const CBuff *buffer)
{
    return (buffer->Head == buffer->Tail);
}

/************************************************************************
* CBuff_IsFull
************************************************************************/
bool CBuff_IsFull(const CBuff *buffer)
{
    return ((buffer->Head + 1) % buffer->Size) == buffer->Tail;
}

/************************************************************************
* CBuff_GetFreeSpace
************************************************************************/
uint32_t CBuff_GetFreeSpace(const CBuff *buffer)
{
    return buffer->Size - CBuff_GetLength(buffer) - 1; 
}


/*************************************************************************************************
*                                   END OF FILE
*************************************************************************************************/

